package com.baoteng.rbspy.service.impl;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mustache.MustacheResourceTemplateLoader;
import org.springframework.stereotype.Service;

import com.baoteng.rbspy.cache.LocalCacheManager;
import com.baoteng.rbspy.config.car.RbSysConfig;
import com.baoteng.rbspy.config.car.URLConfig;
import com.baoteng.rbspy.exception.BizException;
import com.baoteng.rbspy.model.Model;
import com.baoteng.rbspy.model.proposal.DetailsProposal;
import com.baoteng.rbspy.model.proposal.InfoFlow;
import com.baoteng.rbspy.model.proposal.InfoPolicy;
import com.baoteng.rbspy.model.proposal.InfoProposal;
import com.baoteng.rbspy.model.request.proposal.QueryPolicyRequest;
import com.baoteng.rbspy.model.request.proposal.QueryProposalRequest;
import com.baoteng.rbspy.model.response.ResponseModel;
import com.baoteng.rbspy.model.response.pay.CheckCalculate;
import com.baoteng.rbspy.model.response.pay.FeeInfo;
import com.baoteng.rbspy.model.response.pay.PrePay;
import com.baoteng.rbspy.model.response.pay.SavePrePay;
import com.baoteng.rbspy.model.response.pay.WxPrePay;
import com.baoteng.rbspy.model.response.proposal.CheckFlag;
import com.baoteng.rbspy.model.response.proposal.CheckRiskCode;
import com.baoteng.rbspy.model.response.proposal.CheckUndwrt;
import com.baoteng.rbspy.model.response.proposal.InfoUndwrt;
import com.baoteng.rbspy.mq.MessageHandler;
import com.baoteng.rbspy.mq.PackageEntity;
import com.baoteng.rbspy.mq.PackageType;
import com.baoteng.rbspy.mq.WSPackage;
import com.baoteng.rbspy.service.OkHttpClientService;
import com.baoteng.rbspy.service.ProposalService;
import com.baoteng.rbspy.service.QuoteService;
import com.baoteng.rbspy.util.BaseUtil;
import com.baoteng.rbspy.util.BeanConvertUtil;
import com.baoteng.rbspy.util.DateUtil;
import com.baoteng.rbspy.util.DateUtils;
import com.baoteng.rbspy.util.JsoupUtil;
import com.baoteng.rbspy.vo.request.FileMissing;
import com.baoteng.rbspy.vo.request.HeRequest;
import com.baoteng.rbspy.vo.request.PayQrCodeRequset;
import com.baoteng.rbspy.vo.request.UploadFile;
import com.baoteng.rbspy.vo.response.ApplyQuoteResponse;
import com.baoteng.rbspy.vo.response.HeResponse;
import com.baoteng.rbspy.vo.response.PayQrResponse;
import com.baoteng.rbspy.vo.response.SpcialPromise;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.samskivert.mustache.Mustache;

@Service
public class ProposalServiceImpl implements ProposalService {

	private final Logger logger = LoggerFactory.getLogger(ProposalServiceImpl.class);
	
	@Autowired
	OkHttpClientService okHttpClientService;

	@Autowired
	private Mustache.Compiler compiler;

	@Autowired
	MustacheResourceTemplateLoader mustacheTemplateLoader;

	@Autowired
	URLConfig urlConfig;

	@Autowired
	RbSysConfig rbSysConfig;

	BeanConvertUtil beanUtil = BeanConvertUtil.newInstance();

	@Autowired
	LocalCacheManager cache;
	
	@Autowired
	QuoteService quoteService;
	
	@Autowired
	MessageHandler messageHandler;
	
	public boolean delProposal(String proposalNos) {
		ResponseModel<String> response = okHttpClientService.getHtml(
				urlConfig.getProposalDelUrl() + "?bizNo=" + proposalNos,
				String.class);
		return response.isSuccessful();
	}
	
	public Model<InfoPolicy> listPolicy(QueryPolicyRequest request) throws Exception {
		ResponseModel<Model<InfoPolicy>> response = okHttpClientService.postJson(
				urlConfig.getPolicyQueryUrl() + "?pageSize=" + request.getPageSize() + "&pageNo="
						+ request.getPageNo(),
				compiler.compile(mustacheTemplateLoader.getTemplate("policy_query")).execute(request),
				new TypeReference<Model<InfoPolicy>>() {
				});
		return response != null && response.isSuccessful() && response.getBody() != null
				&& response.getBody().getData() != null && response.getBody().getData().size() > 0
						? response.getBody()
						: null;
	}
	
	public Model<InfoProposal> listProposal(QueryProposalRequest request) throws Exception {
		ResponseModel<Model<InfoProposal>> response = okHttpClientService.postJson(
				urlConfig.getProposalQueryUrl() + "?pageSize=" + request.getPageSize() + "&pageNo="
						+ request.getPageNo(),
				compiler.compile(mustacheTemplateLoader.getTemplate("proposal_query")).execute(request),
				new TypeReference<Model<InfoProposal>>() {
				});
		return response != null && response.isSuccessful() && response.getBody() != null
				&& response.getBody().getData() != null && response.getBody().getData().size() > 0
						? response.getBody()
						: null;
	}

	public CheckRiskCode checkRiskCode(String proposalNos) throws Exception {
		if (StringUtils.isBlank(proposalNos)) {
			throw new BizException("投保单号为空");
		}
		ResponseModel<Model<CheckRiskCode>> response = okHttpClientService.getJson(
				urlConfig.getCheckRiskCodeUrl() + "?bizNo=" + proposalNos, new TypeReference<Model<CheckRiskCode>>() {
				});
		if (!response.isSuccessful() || response.getBody() == null || response.getBody().getData() == null
				|| response.getBody().getData().isEmpty()) {
			throw new BizException("险种校验失败");
		}
		return response.getBody().getData().get(0);
	}

	public List<CheckUndwrt> checkUndwrt(String proposalNos) throws Exception {
		if (StringUtils.isBlank(proposalNos)) {
			throw new BizException("投保单号为空");
		}
		ResponseModel<Model<CheckUndwrt>> response = okHttpClientService.getJson(
				urlConfig.getCheckUndwrtUrl() + "?bizNo=" + proposalNos, new TypeReference<Model<CheckUndwrt>>() {
				});
		if (!response.isSuccessful() || response.getBody() == null || response.getBody().getData() == null
				|| response.getBody().getData().isEmpty()) {
			throw new BizException("核保校验失败");
		}
		return response.getBody().getData();
	}

	public void sendCallbackUndwrt(WSPackage<HeRequest> _request,HeResponse response,ApplyQuoteResponse quoteResponse) {
//		sendUndwrtInfo(_request,response);
		WSPackage<HeResponse> _response = new WSPackage<HeResponse>();
		_response.setBizid(_request.getBizid());
		_response.setUserId(_request.getUserId());
		_response.setSessionId(_request.getSessionId());
		response.setBusNum(quoteResponse.getBiNo());
		response.setForceNum(quoteResponse.getCiNo());
		response.setQuoteNum(quoteResponse.getBaojiaNum());
		_response.setData(response);
		_response.setEntity(PackageEntity.ORDER);
		_response.setType(PackageType.LIST);
		messageHandler.producer(_response);
	}
	
	public void sendUndwrtInfo(WSPackage<HeRequest> _request,HeResponse response ) {
		WSPackage<HeResponse> _response = new WSPackage<HeResponse>();
		_response.setBizid(_request.getBizid());
		_response.setUserId(_request.getUserId());
		_response.setSessionId(_request.getSessionId());
		_response.setData(response);
		_response.setEntity(PackageEntity.ORDER);
		_response.setType(PackageType.GET);
		messageHandler.producer(_response);
	}
	
	public HeResponse submitUndwrt(WSPackage<HeRequest> _request) throws Exception {
		HeRequest request = _request.getData();
		if(StringUtils.isBlank(request.getQuoteNum())) {
			throw new BizException("报价单号为空");
		}
		
		Stopwatch watcher = Stopwatch.createStarted();
		ApplyQuoteResponse quoteResponse = quoteService.saveQuote(request.getQuoteNum());
		if(quoteResponse==null || (Strings.isNullOrEmpty(quoteResponse.getBiNo()) && Strings.isNullOrEmpty(quoteResponse.getCiNo()))) {
			if (watcher.isRunning())
				watcher.stop();
			throw new BizException("生成投保单失败");
		}
		request.setBusNum(quoteResponse.getBiNo());
		request.setForNum(quoteResponse.getCiNo());
		if (watcher.elapsed(TimeUnit.SECONDS) >= 60) {
			sendUndwrtInfo(_request,new HeResponse(0, "投保单生成中"));
		}
		if (watcher.isRunning())
			watcher.stop();
		
		String proposalNos = (StringUtils.isNotBlank(quoteResponse.getBiNo())?quoteResponse.getBiNo():"")
				+(StringUtils.isNotBlank(quoteResponse.getCiNo())?","+quoteResponse.getCiNo():"");
		if (StringUtils.isBlank(proposalNos)) {
			throw new BizException("投保单号为空");
		}
		CheckRiskCode CheckRiskCode = checkRiskCode(proposalNos);
		if (!"1".equals(CheckRiskCode.getEnorseno1())) {
			throw new BizException(CheckRiskCode != null && StringUtils.isNotBlank(CheckRiskCode.getEnorseno2())
					? CheckRiskCode.getEnorseno2()
					: "险种校验失败");
		}
		List<CheckUndwrt> checkResult = checkUndwrt(proposalNos);
		StringBuilder errorMsg = new StringBuilder();
		StringBuilder _proposalNos = new StringBuilder();
		// document.getElementById("noNcheckFlag")为1时必须走初审流程，不为1时可以不走初审流程
		for (CheckUndwrt checkUndwrt : checkResult) {
			if ("2".equals(checkUndwrt.getCheckIsNewMakeCom())) {
				sendCallbackUndwrt(_request,new HeResponse(-1, "该操作员未在出单管理系统注册，不允许进行提交核保操作"),quoteResponse);
				throw new BizException("该操作员未在出单管理系统注册，不允许进行提交核保操作");
			}
			String _checkFlag = "4".equals(checkUndwrt.getCheckFlag()) ? "0" : checkUndwrt.getCheckFlag();
			String prpNoStr = "";

			if (checkUndwrt.getUnderWriteFlag().matches("[0|2|F]") && _checkFlag.matches("[0|2]")
					&& !"9".equals(checkUndwrt.getConnectUndWrtFlag())) {
				Date now = new Date();
				int compared = checkUndwrt.getStrStartDate().compareTo(now);
				if (compared < 0 && checkUndwrt.getUnderWriteFlag().matches("[0|2]") && _checkFlag.matches("[0|2]")
						&& !"1".equals(checkUndwrt.getInputFlag())) {
					errorMsg.append("投保单[" + checkUndwrt.getProposalNo() + "]已经起保，不允许提交核保\n");
				} else if (compared == 0 && "2".equals(checkUndwrt.getHourFlag())
						&& checkUndwrt.getUnderWriteFlag().matches("[0|2]")
						&& !"1".equals(checkUndwrt.getInputFlag())) {
					errorMsg.append("投保单[" + checkUndwrt.getProposalNo() + "]已经起保，不允许提交核保\n");
				} else if (checkUndwrt.getUnderWriteFlag().matches("[0|2|F]") && _checkFlag.matches("[0|2]")) {
					prpNoStr = checkUndwrt.getProposalNo();
				} else {
					throw new BizException("_underWriteFlag:" + checkUndwrt.getUnderWriteFlag() + " _:" + _checkFlag
							+ "  _inputFlag:" + checkUndwrt.getInputFlag());
				}
			} else if (checkUndwrt.getUnderWriteFlag().matches("[0|2]") && _checkFlag.matches("[0|2]")
					&& "9".equals(checkUndwrt.getConnectUndWrtFlag())) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "其关联单为待核保状态，不允许提交核保\n");
			}
			if (StringUtils.isNotBlank(prpNoStr) && !"3".equals(checkUndwrt.getCheckIsNewMakeCom())) {
				if (_proposalNos.length() > 0) {
					_proposalNos.append("," + prpNoStr);
				} else {
					_proposalNos.append(prpNoStr);
				}
			}

			if ("0".equals(checkUndwrt.getUnderWriteFlag()) && "3".equals(_checkFlag)) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "初审尚未通过，不允许提交核保\n");
			}
			if (checkUndwrt.getUnderWriteFlag().matches("[0|2]") && "1".equals(_checkFlag)) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "已提交初审，请初审通过后再提交核保\n");
			}
			if (!checkUndwrt.getUnderWriteFlag().matches("[0|2|F]")) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "已经提交核保，不能再提交\n");
			}
			if ("3".equals(checkUndwrt.getCheckIsNewMakeCom()) && StringUtils.isNotBlank(prpNoStr)) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "的出单机构未在出单机构树维护，不允许进行提交核保操作\n");
			}
			if (StringUtils.isNotBlank(checkUndwrt.getContractNo())
					&& "1".equals(checkUndwrt.getContractNo().split(",")[0])) {
				errorMsg.append("投保单" + "[" + checkUndwrt.getProposalNo() + "]" + "为车队团单，请不要由此处提交\n");
			}
			// 广东不做费用审核，其它省份需要费用审核
			// checkSpecialflag =
			// checkSCMFlag(tax.data[i].specialflag,tax.data[i].specialflagConnect,tax.data[i].specialflagRisk,tax.data[i].proposalNo,tax.data[i].unitedSaleflagRisk,tax.data[i].unitedSaleflagZBW);
		}
		if (errorMsg.length() > 0) {
			sendCallbackUndwrt(_request,new HeResponse(-1, "该操作员未在出单管理系统注册，不允许进行提交核保操作"),quoteResponse);
			return new HeResponse(-1, errorMsg.toString());
		}
		if (_proposalNos.length() > 0) {
			// 提交核保
			ResponseModel<String> response = okHttpClientService.getHtml(urlConfig.getSubmitUndwrtUrl() + "?bizNo="
					+ _proposalNos.toString() + "&pageNo=" + 1 + "&pageSize=" + 20, String.class);
			if (!response.isSuccessful() || StringUtils.isBlank(response.getBody())) {
				sendCallbackUndwrt(_request,new HeResponse(0, "提交审核异常"),quoteResponse);
				return new HeResponse(0, "提交审核异常");
//				throw new BizException("提交核保失败");
			}
			String[] numbers = proposalNos.split(",");
			String proposalNo = StringUtils.isNotBlank(numbers[0])?numbers[0]:numbers[1];
			Elements elements = Jsoup.parse(response.getBody()).select("td:contains(" + proposalNo + ")");
			String htmlInfo = null;
			if (elements != null && elements.size() > 0) {
				htmlInfo = elements.get(0).text().replaceAll("核保意见", "");
			}
			if(htmlInfo != null && htmlInfo.indexOf("预核保转人工状态")!=-1) {
				logger.info("商业险投保单号:{},交强险投保单号:{}-预核保转人工状态",quoteResponse.getBiNo(),quoteResponse.getCiNo());
				// 再次提交核保
				ResponseModel<String> _response = okHttpClientService.getHtml(urlConfig.getSubmitUndwrtUrl() + "?bizNo="
						+ _proposalNos.toString() + "&pageNo=" + 1 + "&pageSize=" + 20, String.class);
				if (!_response.isSuccessful() || StringUtils.isBlank(_response.getBody())) {
					sendCallbackUndwrt(_request,new HeResponse(0, "提交审核异常"),quoteResponse);
					return new HeResponse(0, "提交审核异常");
				}
				Elements _elements = Jsoup.parse(response.getBody()).select("td:contains(" + proposalNo + ")");
				if (_elements != null && _elements.size() > 0) {
					htmlInfo = _elements.get(0).text().replaceAll("核保意见", "");
				}
			}
			if (htmlInfo != null && htmlInfo.indexOf("投保预确认失败") != -1) {
				if(htmlInfo.indexOf("税务机关名称不一致")!=-1 || htmlInfo.indexOf("税务机关代码不一致")!=-1) {//上传完税证明
					HeResponse taxResposne = new HeResponse();
					taxResposne.setForceNum(request.getForNum());
					taxResposne.setBusNum(request.getBusNum());
					taxResposne.setQuoteNum(request.getQuoteNum());
					taxResposne.setBusinessStatus(3);
					taxResposne.setStatusMessage(htmlInfo);
					FileMissing missing = new FileMissing();
					missing.setFileType("T07");
					List<UploadFile> uploadList = Lists.newArrayList();
					UploadFile uploadFile = new UploadFile();
					uploadFile.setSubType("TAX01");
					uploadFile.setSubTypeDesc("完税证明");
					uploadList.add(uploadFile);
					missing.setSubFiles(uploadList);
					taxResposne.setMissings(Lists.newArrayList(missing));
					sendCallbackUndwrt(_request,taxResposne,quoteResponse);
					return taxResposne;
				}
				sendCallbackUndwrt(_request,new HeResponse(-1, htmlInfo),quoteResponse);
				return new HeResponse(-1, htmlInfo);
			}
			HeResponse undwrtinfo = getUndwrtInfo(proposalNos);
			sendCallbackUndwrt(_request,undwrtinfo,quoteResponse);
			return undwrtinfo;
		}
		sendCallbackUndwrt(_request,new HeResponse(-2, "提交核保失败"),quoteResponse);
		return new HeResponse(-2, "提交核保失败");
	}

	public HeResponse getUndwrtInfo(String proposalNos) throws Exception {
		if (StringUtils.isBlank(proposalNos)) {
			throw new BizException("投保单号为空");
		}
		String[] _proposalNos = proposalNos.split(",");
		QueryProposalRequest request = new QueryProposalRequest();
		if(_proposalNos!=null && _proposalNos.length>=2) {
			if(StringUtils.isNotBlank(_proposalNos[0])) {
				request.setProposalNo(_proposalNos[0]);
			}else {
				request.setProposalNo(_proposalNos[1]);
			}
		}else if(_proposalNos!=null && _proposalNos.length>0) {
			request.setProposalNo(_proposalNos[0]);
		}
		
		Model<InfoProposal> pList = listProposal(request);
		/**
		 * 核保状态 0--待核保 1--待缴费 -1--核保不通过 -2--待同步
		 */
		int status = 0;
		if (pList != null && pList.getData()!=null && pList.getData().size() > 0) {
			for (InfoProposal proposal : pList.getData()) {
				if (proposal.getUnderWriteFlag().contains("待核保")) {
					status += 0;
				} else if (proposal.getUnderWriteFlag().contains("不通过")) {
					status += -1;
				} else if (proposal.getUnderWriteFlag().contains("待同步")) {
					status += -1;
				} else if (proposal.getUnderWriteFlag().contains("初始值")) {
					status += 0;
				} else if (proposal.getUnderWriteFlag().contains("见费出单待缴费")) {
					status += 1;
				}
			}
		}else {
			return new HeResponse(-1, "投保单不存在，可能已经被删除。");
		}
		HeResponse heResponse = new HeResponse(0, "待核保");
		Stream.of(_proposalNos).forEach(p->{
			if(StringUtils.isNotBlank(p)) {
				if(p.indexOf("DAA")>-1) {
					heResponse.setBusNum(p);
				}else {
					heResponse.setForceNum(p);
				}
			}
		});
		if (status == 1*pList.getData().size()) {
			heResponse.setStatusMessage("ok");
			heResponse.setBusinessStatus(1);
			DetailsProposal detail = getProposalInfo(Optional.ofNullable(heResponse.getBusNum()).orElse(heResponse.getForceNum()));
			if(detail==null) {
				return new HeResponse(-1, "投保单不存在，可能已经被删除。");
			}
			heResponse.setSumPremium(detail.getSumPremium());
			heResponse.setSumPayTax(detail.getSumPayTax());
			heResponse.setSumPay(BaseUtil.getMoneyNumber(detail.getSumPremium().doubleValue()+(detail.getSumPayTax()!=null?detail.getSumPayTax().doubleValue():0)));
			getProposalClause(heResponse);
			return heResponse;
		}else if (status >= 0 && status <=1) {
			return heResponse;
		}
		if(status<0) status=-1;
		StringBuilder sb = new StringBuilder();
		List<FileMissing> missings = Lists.newArrayList();
		for (String proposalNo : _proposalNos) {
			if(StringUtils.isBlank(proposalNo)) continue;
			ResponseModel<String> response = okHttpClientService
					.getHtml(urlConfig.getInfoUndwrtUrl() + "?bizNo=" + proposalNo + "&bizType=PROPOSAL", String.class);
			if (!response.isSuccessful() || StringUtils.isBlank(response.getBody())) {
				throw new BizException("获取核保意见失败");
			}
			Elements elements = Jsoup.parse(response.getBody()).select("#insertUndwrtRow>tbody>tr");
			if (elements != null && elements.size() > 0) {
				List<InfoUndwrt> undwrts = Lists.newArrayList();
				Date lastTime = null;
				for (int i = elements.size() - 1; i >= 0; i--) {
					InfoUndwrt undwrt = new InfoUndwrt();
					JsoupUtil.newInstance().parse(elements.get(i), undwrt);
					if (lastTime == null) {
						lastTime = DateUtil.fromString(undwrt.getOutDateString());
						undwrts.add(undwrt);
					} else if (lastTime.compareTo(DateUtil.fromString(undwrt.getOutDateString())) == 0) {
						undwrts.add(undwrt);
					} else {
						break;
					}
				}
				sb.append(proposalNo.contains("DAA") ? "商业险核保信息：" : "交强险核保信息：");
				for (int j = undwrts.size() - 1; j >= 0; j--) {
					sb.append(StringUtils.isNotBlank(undwrts.get(j).getHandleText()) ? undwrts.get(j).getHandleText()
							: "");
				}
				String handleText = sb.toString();
				if (handleText.contains("验车")) {
					status = 2;
					FileMissing missing = new FileMissing();
					missing.setFileType("T02");
					List<UploadFile> uploadList = Lists.newArrayList();
					UploadFile uploadFile = new UploadFile();
					uploadFile.setSubType("TAR07");
					uploadFile.setSubTypeDesc("广州地标验车相");
					uploadList.add(uploadFile);
					missing.setSubFiles(uploadList);
					missings.add(missing);
					if (handleText.contains("行驶证")) {
						FileMissing _missing = new FileMissing();
						_missing.setFileType("T04");
						List<UploadFile> _uploadList = Lists.newArrayList();
						UploadFile _uploadFile = new UploadFile();
						_uploadFile.setSubType("TAR04");
						_uploadFile.setSubTypeDesc("行驶证");
						_uploadList.add(_uploadFile);
						_missing.setSubFiles(_uploadList);
						missings.add(_missing);
					}
					if (handleText.contains("身份证")) {
						UploadFile _uploadFile = new UploadFile();
						_uploadFile.setSubType("001");
						_uploadFile.setSubTypeDesc("身份证");
						uploadList.add(_uploadFile);
					}
				} else {
					if (handleText.contains("本地使用证明")) {
						status = 3;
						FileMissing missing = new FileMissing();
						missing.setFileType("T06");
						List<UploadFile> uploadList = Lists.newArrayList();
						UploadFile uploadFile = new UploadFile();
						uploadFile.setSubType("TAR08");
						uploadFile.setSubTypeDesc("本地使用证明");
						uploadList.add(uploadFile);
						missing.setSubFiles(uploadList);
						missings.add(missing);
						if (handleText.contains("行驶证")) {
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("TAR04");
							_uploadFile.setSubTypeDesc("行驶证");
							uploadList.add(_uploadFile);

						}
						if (handleText.contains("上年保单")) {
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("TAR04");
							_uploadFile.setSubTypeDesc("上年保单");
							uploadList.add(_uploadFile);
						}
						missings.add(missing);
					}else if(handleText.contains("核实是否过户")) {
						status = 3;
						FileMissing missing = new FileMissing();
						missing.setFileType("T04");
						List<UploadFile> uploadList = Lists.newArrayList();
						UploadFile uploadFile = new UploadFile();
						uploadFile.setSubType("TAR04");
						uploadFile.setSubTypeDesc("行驶证");
						uploadList.add(uploadFile);
						missing.setSubFiles(uploadList);
						missings.add(missing);
						
						FileMissing _missing = new FileMissing();
						_missing.setFileType("T02");
						List<UploadFile> _uploadList = Lists.newArrayList();
						UploadFile _uploadFile = new UploadFile();
						_uploadFile.setSubType("001");
						_uploadFile.setSubTypeDesc("身份证");
						_uploadList.add(_uploadFile);
						_missing.setSubFiles(_uploadList);
						missings.add(_missing);
					}
					else {
						if (handleText.contains("行驶证")) {
							status = 3;
							FileMissing _missing = new FileMissing();
							_missing.setFileType("T04");
							List<UploadFile> _uploadList = Lists.newArrayList();
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("TAR04");
							_uploadFile.setSubTypeDesc("行驶证");
							_uploadList.add(_uploadFile);
							_missing.setSubFiles(_uploadList);
							missings.add(_missing);
						}
						if (handleText.contains("上年保单")) {
							status = 3;
							FileMissing _missing = new FileMissing();
							_missing.setFileType("T04");
							List<UploadFile> _uploadList = Lists.newArrayList();
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("TAR04");
							_uploadFile.setSubTypeDesc("上年保单");
							_uploadList.add(_uploadFile);
							_missing.setSubFiles(_uploadList);
							missings.add(_missing);
						}
						if (handleText.contains("身份证")) {
							status = 3;
							FileMissing _missing = new FileMissing();
							_missing.setFileType("T01");
							List<UploadFile> _uploadList = Lists.newArrayList();
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("001");
							_uploadFile.setSubTypeDesc("身份证");
							_uploadList.add(_uploadFile);
							_missing.setSubFiles(_uploadList);
							missings.add(_missing);
						}
						if (handleText.contains("机动车辆登记证书")) {
							status = 3;
							FileMissing _missing = new FileMissing();
							_missing.setFileType("T04");
							List<UploadFile> _uploadList = Lists.newArrayList();
							UploadFile _uploadFile = new UploadFile();
							_uploadFile.setSubType("TAR05");
							_uploadFile.setSubTypeDesc("机动车辆登记证书");
							_uploadList.add(_uploadFile);
							_missing.setSubFiles(_uploadList);
							missings.add(_missing);
						}
					}
				}
			}
		}
		if (missings.size() > 0) {
			missings = missings.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(FileMissing::getFileType))),ArrayList::new));
			heResponse.setMissings(missings);
		}
		heResponse.setBusinessStatus(status);
		heResponse.setStatusMessage(sb.toString());
		return heResponse;
	}
	
	public List<SpcialPromise> getProposalClause(HeResponse heResponse){
		if(heResponse!=null && !StringUtils.isAllBlank(heResponse.getBusNum(),heResponse.getForceNum())) {
			String riskCode = StringUtils.isNotBlank(heResponse.getBusNum())?"DAA":"DZA";
			String num= StringUtils.isNotBlank(heResponse.getBusNum())?heResponse.getBusNum():heResponse.getForceNum();
			ResponseModel<HeResponse> proposal = okHttpClientService.getHtml(StringUtils.join(urlConfig.getClauseUrl(),
					"?systemCode=&editType=SHOW_PROPOSAL&bizType=PROPOSAL"
					,"&bizNo=",num
					,"&riskCode=",riskCode
					,"&minusFlag=&contractNo=&comCode=",rbSysConfig.getComCode()
					,"&originQuery=&beiRenewalFlag=&proposalNo=",num), HeResponse.class);
			if( proposal.isSuccessful()&& proposal.getBody()!=null
					&& proposal.getBody().getBusSpecialLists()!=null && proposal.getBody().getBusSpecialLists().size()>0) {
				 List<SpcialPromise> clauses = proposal.getBody().getBusSpecialLists();
				 clauses = clauses.stream().filter(c->{
					 if(StringUtils.isNotBlank(c.getPromiseCode()) && c.getPromiseCode().trim().equals("996063")) {
						 return false;
					 }
					 return true;
				 }).collect(Collectors.toList());
				if(clauses!=null && clauses.size()>0) heResponse.setBusSpecialLists(clauses);
				return proposal.getBody().getBusSpecialLists();
			}
		}
		return null;
	}
	
	public DetailsProposal getProposalInfo(String proposalNo) {
		ResponseModel<DetailsProposal> proposal = okHttpClientService.getHtml(urlConfig.getProposalGetUrl()+"?bizNo="+proposalNo, DetailsProposal.class);
		return proposal.isSuccessful()&& proposal.getBody()!=null
				&& (proposalNo.equals(proposal.getBody().getProposalNoBI()) || proposalNo.equals(proposal.getBody().getProposalNoCI()))
				?proposal.getBody():null;
	}
	
	public InfoFlow getFlow(String proposalNo) {
		ResponseModel<InfoFlow> proposal = okHttpClientService.getHtml(urlConfig.getShowFlowUrl()+"?bizNo="+proposalNo, InfoFlow.class);
		final InfoFlow  flow =proposal.getBody();
		if(proposal.isSuccessful()&& proposal.getBody()!=null && proposalNo.equals(proposal.getBody().getBizNo()) && proposal.getBody().getDetails()!=null && proposal.getBody().getDetails().size()>0) {
			proposal.getBody().getDetails().forEach(f->{
				String nodeTime = f.getNodeTime();
				if(StringUtils.isNotBlank(f.getNodeTitle()) && f.getNodeTitle().contains(":缴费") && StringUtils.isNotBlank(nodeTime)) {
					String _payTime = nodeTime.replaceAll("处理时间:", "");
					flow.setPayTime(DateUtils.parseDateByFormat(_payTime, "yyyy-MM-dd HH:mm:ss"));
				}
			});
		}
		return flow;
	}
	
	/**
	 * 生成缴费通知单
	 */
	public PayQrResponse getExchange(PayQrCodeRequset request) throws Exception {
		String quoteNum = StringUtils.isNotBlank(request.getBusNum())?request.getBusNum():(StringUtils.isNotBlank(request.getForNum())?request.getForNum():request.getQuoteNum());
		
		request.setQuoteNum(quoteNum);
		ResponseModel<Model<CheckFlag>> checkResponse = okHttpClientService.getJson(
				urlConfig.getEditCheckFlagUrl() + "?bizNo=" + quoteNum,
				new TypeReference<Model<CheckFlag>>() {
				});
		if (!checkResponse.isSuccessful() || checkResponse.getBody() == null
				|| checkResponse.getBody().getData() == null) {
			throw new BizException("投保单状态检测失败");
		}
		if (checkResponse.getBody().getData().isEmpty()) {
			throw new BizException("投保单" + request.getQuoteNum() + "不存在。");
		}
		CheckFlag checkFlag = checkResponse.getBody().getData().get(0);
		if (!"4".equals(checkFlag.getUnderWriteFlag()) && !"5".equals(checkFlag.getUnderWriteFlag())) {
			throw new BizException("投保单" + request.getQuoteNum() + "不是待缴费状态。");
		}
		ResponseModel<PrePay> preJfResponse = okHttpClientService.getHtml(
				urlConfig.getPreJFUrl() + "?workbenchUserCode="
						+ checkResponse.getBody().getData().get(0).getCheckUpCode() + "&workbenchCertiNo="
						+ quoteNum + "&worekbenchUserComCode=" + this.rbSysConfig.getComCode(),
				PrePay.class);
		if (!preJfResponse.isSuccessful() || preJfResponse.getBody() == null) {
			throw new BizException("获取缴费通知单失败");
		}
		PrePay prePay = preJfResponse.getBody();
		boolean isNew = false;
		if (StringUtils.isNotBlank(prePay.getExchangeNo())) {
			ResponseModel<PrePay> _mainJfResponse = okHttpClientService
					.getHtml(urlConfig.getPreJfMainUrl() + "?exchangeNo=" + prePay.getExchangeNo(), PrePay.class);
			if (!_mainJfResponse.isSuccessful() || _mainJfResponse.getBody() == null) {
				throw new BizException("获取缴费通知单失败");
			}
			PrePay mainPrePay = _mainJfResponse.getBody();
			if ("2".equals(mainPrePay.getPayState()) || "3".equals(mainPrePay.getPayState())) {
				throw new BizException("投保单状态为已交费");
			}
			if ("4".equals(mainPrePay.getPayState())) {
				isNew = true;
			} else {
				if (StringUtils.isNotBlank(mainPrePay.getLatestPayDate())) {
					Date latestPaydate = null;
					if (mainPrePay.getLatestPayDate().length() == 10) {
						latestPaydate = DateUtils.parseDateByFormat(mainPrePay.getLatestPayDate() + " 23:59:59",
								"yyyy-MM-dd HH:mm:ss");
						if (latestPaydate.getTime() <= System.currentTimeMillis()) {
							isNew = true;
						}
					} else {
						latestPaydate = DateUtil.fromString(_mainJfResponse.getBody().getLatestPayDate());
					}
					if (latestPaydate == null) {
						isNew = true;
					}
				} else {
					isNew = true;
				}
			}
		} else {
			isNew = true;
		}
		if (isNew) {
			prePay = saveExchange(request);
		}
		String wxQR = getWeixinQR(prePay.getExchangeNo());
		PayQrResponse response = new PayQrResponse();
		response.setBusinessStatus(1);
		response.setStatusMessage("ok");
		response.setUrl(wxQR);
		return response;
	}

	public PrePay saveExchange(PayQrCodeRequset request) throws Exception {
		ResponseModel<Model<CheckFlag>> checkResponse = okHttpClientService.getJson(
				urlConfig.getEditCheckFlagUrl() + "?bizNo=" + request.getQuoteNum(),
				new TypeReference<Model<CheckFlag>>() {
				});
		if (!checkResponse.isSuccessful() || checkResponse.getBody() == null
				|| checkResponse.getBody().getData() == null) {
			throw new BizException("投保单状态检测失败");
		}
		if (checkResponse.getBody().getData().isEmpty()) {
			throw new BizException("投保单" + request.getQuoteNum() + "不存在。");
		}
		CheckFlag checkFlag = checkResponse.getBody().getData().get(0);
		if (!"4".equals(checkFlag.getUnderWriteFlag()) && !"5".equals(checkFlag.getUnderWriteFlag())) {
			throw new BizException("投保单" + request.getQuoteNum() + "不是待缴费状态。");
		}
		ResponseModel<PrePay> preJfResponse = okHttpClientService.getHtml(
				urlConfig.getPreJFUrl() + "?workbenchUserCode="
						+ checkResponse.getBody().getData().get(0).getCheckUpCode() + "&workbenchCertiNo="
						+ request.getQuoteNum() + "&worekbenchUserComCode=" + this.rbSysConfig.getComCode(),
				PrePay.class);
		if (!preJfResponse.isSuccessful() || preJfResponse.getBody() == null) {
			throw new BizException("生成交费通知单失败");
		}
		String jfPre = compiler.compile(mustacheTemplateLoader.getTemplate("jf_pre")).execute(preJfResponse.getBody());

		ResponseModel<Model<CheckCalculate>> checkCalculateResponse = okHttpClientService
				.postJson(urlConfig.getCheckCalculateUrl(), jfPre, new TypeReference<Model<CheckCalculate>>() {
				});
		if (!checkCalculateResponse.isSuccessful() || checkCalculateResponse.getBody() == null
				|| checkCalculateResponse.getBody().getData() == null
				|| checkCalculateResponse.getBody().getData().isEmpty()) {
			throw new BizException("投保单保存校验失败");
		}
		CheckCalculate checkCalculate = checkCalculateResponse.getBody().getData().get(0);
		if (!"1".equals(checkCalculate.getCheck1())) {
			throw new BizException(checkCalculate.getCheck2());
		}

		ResponseModel<Model<SavePrePay>> saveResponse = okHttpClientService.postJson(urlConfig.getSaveJFUrl(), jfPre,
				new TypeReference<Model<SavePrePay>>() {
				});
		if (!saveResponse.isSuccessful() || saveResponse.getBody() == null
				|| saveResponse.getBody().getData() == null) {
			throw new BizException("生成缴费通知单失败");
		}
		if (StringUtils.isNotBlank(saveResponse.getBody().getMsg())) {
			throw new BizException(saveResponse.getBody().getMsg());
		}

		SavePrePay savePrePay = saveResponse.getBody().getData().get(0);
		if (StringUtils.isNotBlank(savePrePay.getFlag())) {
			throw new BizException("积分锁定失败");
		}
		PrePay prePay = new PrePay();
		prePay.setExchangeNo(savePrePay.getSCol1());
		prePay.setLatestPayDate(savePrePay.getSCol8());
		prePay.setSumFee(StringUtils.isNotBlank(savePrePay.getSCol7()) ? Double.valueOf(savePrePay.getSCol7()) : null);
		prePay.setSumQuantity(
				StringUtils.isNotBlank(savePrePay.getSCol6()) ? Integer.valueOf(savePrePay.getSCol6()) : null);
		prePay.setRegistCode(savePrePay.getSCol3());
		prePay.setRegistCodeName(savePrePay.getSCol5());
		prePay.setComCode(savePrePay.getSCol2());
		prePay.setComCodeName(savePrePay.getSCol4());

		return prePay;
	}

	public void cancelWeixinQR(WxPrePay wxPrePay) throws Exception {
		ResponseModel<String> wxResponse = okHttpClientService
				.postHtml(urlConfig.getCancelWeixinUrl() + "?exchangeNo=" + wxPrePay.getExchangeNo() + "&serialNo="
						+ wxPrePay.getSerialNo() + "&payType=" + wxPrePay.getPayType(), "", String.class);
		if (!wxResponse.isSuccessful()) {
			throw new BizException("取消微信支付二维码失败");
		}
	}

	public WxPrePay newWeixinQR(String exchangeNo) throws Exception {
		ResponseModel<WxPrePay> wxResponse = okHttpClientService
				.getHtml(urlConfig.getNewWeixinUrl() + "?exchangeNo=" + exchangeNo + "&wechatFlag=NEW", WxPrePay.class);
		if (!wxResponse.isSuccessful() || wxResponse.getBody() == null) {
			throw new BizException("生成微信支付二维码失败");
		}
		WxPrePay _wxPrePay = wxResponse.getBody();
		String strWx = compiler.compile(mustacheTemplateLoader.getTemplate("jf_wechat")).execute(_wxPrePay);
		ResponseModel<String> result = null;
		if (StringUtils.isBlank((_wxPrePay.getFlag()))) {
			_wxPrePay.setFlag("1");
			result = okHttpClientService.postHtml(urlConfig.getSaveWeixinUrl()+"?payType="+_wxPrePay.getPayType()+"&type="+_wxPrePay.getFlag(), strWx, String.class);
			if (!result.isSuccessful()) {
				throw new BizException("交费登记失败");
			}
			_wxPrePay.setFlag("3");
		}
		strWx = compiler.compile(mustacheTemplateLoader.getTemplate("jf_wechat")).execute(_wxPrePay);
		result = okHttpClientService.postHtml(urlConfig.getSaveWeixinUrl()+"?payType="+_wxPrePay.getPayType()+"&type="+_wxPrePay.getFlag(), strWx, String.class);
		if (!result.isSuccessful()) {
			throw new BizException("交费登记确认失败");
		}
		_wxPrePay.setFlag("3");
		return _wxPrePay;
	}

	public WxPrePay updateWeixinQR(FeeInfo feeInfo) throws Exception {
		if ("1".equals(feeInfo.getFlag())) {
			ResponseModel<WxPrePay> wxResponse = okHttpClientService.getHtml(urlConfig.getNewWeixinUrl()
					+ "?exchangeNo=" + feeInfo.getCheckNo() + "&serialNo=" + feeInfo.getSerialNo() + "&payNo="
					+ feeInfo.getPayNo() + "&flag=" + feeInfo.getFlag() + "&ModifyFlag=DENGJI", WxPrePay.class);
			if (!wxResponse.isSuccessful() || wxResponse.getBody() == null) {
				throw new BizException("交费登记失败");
			}
			WxPrePay _wxPrePay = wxResponse.getBody();
			_wxPrePay.setFlag("3");
			String strWx = compiler.compile(mustacheTemplateLoader.getTemplate("jf_wechat")).execute(_wxPrePay);
			ResponseModel<String> result = okHttpClientService.postHtml(urlConfig.getSaveWeixinUrl()+"?payType="+_wxPrePay.getPayType()+"&type="+_wxPrePay.getFlag(), strWx,
					String.class);
			if (!result.isSuccessful()) {
				throw new BizException("交费登记确认失败");
			}
			_wxPrePay.setFlag("3");
			return _wxPrePay;
		}
		return null;
	}

	/**
	 * 获取微信支付二维码
	 * 
	 * @param request
	 * @throws Exception
	 */
	public String getWeixinQR(String exchangeNo) throws Exception {
		ResponseModel<String> infoResponse = okHttpClientService.getHtml(
				urlConfig.getPayInfoUrl() + "?exchangeNo=" + exchangeNo + "&pageNo=1&pageSize=50", String.class);
		if (!infoResponse.isSuccessful() || StringUtils.isBlank(infoResponse.getBody())) {
			throw new BizException("支付信息查询失败");
		}
		Document doc = Jsoup.parse(infoResponse.getBody());
		List<FeeInfo> fees = Lists.newArrayList();
		Element element = doc.getElementById("insertPayFeeRow");
		if (element != null) {
			Elements elements = element.select("tbody>tr");
			elements.forEach(e -> {
				FeeInfo feeInfo = new FeeInfo();
				JsoupUtil.newInstance().parse(e, feeInfo);
				if (feeInfo != null && "9".equals(feeInfo.getPayType())
						&& ("交费登记".equals(feeInfo.getPayState()) || "登记确认".equals(feeInfo.getPayState()))) {
					fees.add(feeInfo);
				}
			});
		}
		if (fees.size() > 0) {
			FeeInfo feeInfo = fees.get(0);
			if ("交费登记".equals(feeInfo.getPayState())) {
				updateWeixinQR(feeInfo);
			}
			ResponseModel<WxPrePay> wxResponse = okHttpClientService.getHtml(
					urlConfig.getGetQrUrl() + "?exchangeNo=" + exchangeNo + "&serialNo=" + feeInfo.getSerialNo()
							+ "&payNo=" + feeInfo.getPayNo() + "&flag=" + feeInfo.getFlag() + "&ModifyFlag=QUEREN",
					WxPrePay.class);
			if (!wxResponse.isSuccessful() || wxResponse.getBody() == null
					|| StringUtils.isBlank(wxResponse.getBody().getQrUrl())) {
				throw new BizException("生成支付二维码失败");
			}
			WxPrePay wxPrePay = wxResponse.getBody();
			String memo = wxPrePay.getMemo();
			if (StringUtils.isNotBlank(memo)) {
				String _memo = memo.substring(memo.indexOf("2"),
						(memo.indexOf("2") + 19) > memo.length() ? memo.length() : (memo.indexOf("2") + 19));
				try {
					Date expireTime = DateUtil.fromString(BaseUtil.matchNumberAndLetters(_memo));
					if (expireTime != null && expireTime.getTime() > System.currentTimeMillis()) {
						String qrUrl = wxPrePay.getQrUrl();
						return qrUrl.substring(qrUrl.indexOf("=") + 1,
								qrUrl.indexOf("&") != -1 ? qrUrl.indexOf("&") : qrUrl.length());
					}
				} catch (Exception e) {
					String qrUrl = wxPrePay.getQrUrl();
					return qrUrl.substring(qrUrl.indexOf("=") + 1,
							qrUrl.indexOf("&") != -1 ? qrUrl.indexOf("&") : qrUrl.length());
				}
			} else if (!"3".equals(wxPrePay.getFlag())) {
				throw new BizException("支付状态无效，请联系客服确认");
			}
			cancelWeixinQR(wxPrePay);
		}
		newWeixinQR(exchangeNo);
//		ResponseModel<WxPrePay> wxResponse = okHttpClientService.getHtml(
//				urlConfig.getGetQrUrl() + "?exchangeNo=" + exchangeNo + "&serialNo=" + wxPrePay.getSerialNo()
//						+ "&payNo=" + (StringUtils.isBlank(wxPrePay.getPayNo())?wxPrePay.getSerialNo():wxPrePay.getPayNo()) + "&flag=" + wxPrePay.getFlag() + "&ModifyFlag=QUEREN",
//				WxPrePay.class);
//		if (!wxResponse.isSuccessful() || wxResponse.getBody() == null
//				|| StringUtils.isBlank(wxResponse.getBody().getQrUrl())) {
//			throw new BizException("生成支付二维码失败");
//		}
//		wxPrePay = wxResponse.getBody();
//		String qrUrl = wxPrePay.getQrUrl();
//		return qrUrl.substring(qrUrl.indexOf("=") + 1, qrUrl.indexOf("&") != -1 ? qrUrl.indexOf("&") : qrUrl.length());
		return getWeixinQR(exchangeNo);
	}

}
